// 19/11/2018

load "Data_Zywina.m";

//////////////////////////////////////////////////////////////////////
//
//  ........
//
//////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////
//Below is the code to compute the data found in FiberProductsData.m


FP := recformat< level:RngIntElt,curve:CrvPln,curve1:Crv, group:GrpMat, genus:RngIntElt>;
//for each possible mod p and q image (with p<q) whose modli space is genus 0, compute
//the fiber product of their moduli spaces and create a record of that includes the
//level, curve, and corresponds group of level p*q.
FiberProducts := AssociativeArray();
for g1,g2 in [k : k in Keys(Groups)] do
    if Groups[g1]`level lt Groups[g2]`level and PrimeFactors(Groups[g1]`level) ne PrimeFactors(Groups[g2]`level) thens
	   	G1 := Groups[g1]`group;
   		G2 := Groups[g2]`group;
    	G := LiftGroups(G1,G2);
    	T1 := TorsionType(G1);
    	T2 := TorsionType(G2);
    	T := [T1[1]*T2[1],T1[2]*T2[2]];
    	N := IsogenyDegree(G1)*IsogenyDegree(G2);
    	if N in NonCMIsogDegrees and T in PossibleTorsion then
			FiberProducts[[g1,g2]] := rec<FP|level:=Groups[g1]`level*Groups[g2]`level,curve:=FiberProduct_Curve(g1,g2), group:=G, genus:=GL2Genus(G)>;
		end if;
    end if;
end for;
    


////////////////////////////////////////////////////////////////////////
//Below is the code to compute the data at the lists CurvesByGenus[g]

CurvesByGenus := AssociativeArray();

genera:={FiberProducts[k]`genus : k in Keys(FiberProducts)};

for g in genera do
   CurvesByGenus[g] := Sort([k  : k in Keys(FiberProducts) | g eq FiberProducts[k]`genus]);
end for;


/////////////////////////////////////////////////////////////


print "--- Genus g - #CurvesByGenus[g] ---";
for g in Sort(Setseq(Keys(CurvesByGenus))) do 
	g, #CurvesByGenus[g];
end for;



/////////////////////////////////////////////////////////////


fprintf "FiberProductsData.m", "F<t> := FunctionField(Rationals());\n\n\n";

// Print the Groups data.

fprintf "FiberProductsData.m", "Groups := AssociativeArray();\n";
fprintf "FiberProductsData.m", "grp := recformat< level:IntegerRing(), group:GrpMat, jmap:FldFunRatUElt>;\n\n\n";

for k in Keys(Groups) do 
	rec := Groups[k];
	if k ne "11Nn" then
		fprintf "FiberProductsData.m", "Groups[\"%o\"] := rec<grp| level:=%o, group:=sub<GL(2,Integers(%o)) | %o>, jmap := %o>;\n",k, rec`level,rec`level, [ElementToSequence(g) : g in Generators(rec`group)], rec`jmap;
	end if;
	if k eq "11Nn" then
		fprintf "FiberProductsData.m", "Groups[\"%o\"] := rec<grp| level:=%o, group:=sub<GL(2,Integers(%o)) | %o>>;\n",k, rec`level,rec`level, [ElementToSequence(g) : g in Generators(rec`group)];
	end if;
end for;


//Print the FiberProducts data

fprintf "FiberProductsData.m", "FiberProducts := AssociativeArray();\n";
fprintf "FiberProductsData.m", "R<X,Y,Z> := PolynomialRing(Rationals(),3);\n";
fprintf "FiberProductsData.m", "FP := recformat< level:RngIntElt,curve:CrvPln,curve1:Crv, group:GrpMat, genus:RngIntElt>;\n\n";


for k in Keys(FiberProducts) do 
	rec := FiberProducts[k];
	R<X,Y,Z> := PolynomialRing(Rationals(),3);
	C:=rec`curve;
	pol := R!DefiningPolynomial(C);
	P := ProjectiveSpace(Rationals(),2);
	fprintf "FiberProductsData.m", "FiberProducts[[\"%o\",\"%o\"]] := rec<FP|level:=%o,curve:=Curve(ProjectiveSpace(Rationals(),2),%o), group:=sub<GL(2,Integers(%o)) | %o>, genus:=%o>;\n",k[1],k[2],rec`level, pol, rec`level,[ElementToSequence(g) : g in Generators(rec`group)], rec`genus;
end for;


//Print the CurvesByGenus data

fprintf "FiberProductsData.m", "%o", "CurvesByGenus := AssociativeArray();\n";
for g in Sort(Setseq(Keys(CurvesByGenus))) do
	list := CurvesByGenus[g];
	fprintf "FiberProductsData.m", "CurvesByGenus[%o] := [\n",g;
	for i in [1..#list] do
		k := list[i];
		if i ne #list then
			fprintf "FiberProductsData.m", "[\"%o\",\"%o\"],\n", k[1],k[2];
		end if;
		if i eq #list then
			fprintf "FiberProductsData.m", "[\"%o\",\"%o\"]\n", k[1],k[2];
		end if;		
	end for;
	fprintf "FiberProductsData.m", "];\n";
end for;


